#ifndef ANTLIST_HPP
#define ANTLIST_HPP

#include "location.hpp"
#include "wavemap.hpp"

#include <map>
#include <vector>
#include <iterator>

struct locless
{
  bool operator()( location left, location right ) const
  {
    if (left.row == right.row )
      return  left.col < right.col;
    return left.row < right.row;
  }
};

struct rowless
{
  bool operator()( location left, location right ) const
  {
    return left.row < right.row;
  }
};

struct colless
{
  bool operator()( location left, location right ) const
  {
    return left.col < right.col;
  }
};


class antlist
{
  /*typedef std::set<location, locless> locmap;
  typedef std::multiset<location, rowless> rowmap;
  typedef std::multiset<location, colless> colmap;
  */
  typedef wavemap::field_t field_t;
  typedef std::multimap<field_t, location> weightmap;
  typedef std::map< location, weightmap> targetmap;
  typedef weightmap::iterator w_iterator;
  typedef weightmap::reverse_iterator w_reverse_iterator; 

  typedef targetmap::iterator t_iterator;
  typedef targetmap::const_iterator t_const_iterator;
  typedef targetmap::reverse_iterator t_reverse_iterator; 

public:
  antlist()
    :_wavemap(0)
  {
  }

  void create(wavemap *wm)
  {
    _wavemap = wm;
    _targets.clear();
  }

  size_t size() const 
  {
    /*return _weightmap.size();
     * */
    size_t s = 0;
    t_const_iterator tbeg = _targets.begin();
    t_const_iterator tend = _targets.end();
    for ( ;tbeg!=tend; ++tbeg)
      s += tbeg->second.size();
    return s;

  }

  bool add( location loc )
  {
    field_t weight = _wavemap->get(loc);
    if ( weight!=255 )
       _targets[ _wavemap->target(loc) ].insert( std::make_pair( weight , loc ) );
    else
      return false;
    return true;
      
  }
  
  void remove( location loc )
  {
    t_iterator tbeg = _targets.begin();
    t_iterator tend = _targets.end();
    for ( ;tbeg!=tend; ++tbeg)
    {
      w_iterator beg = tbeg->second.begin();
      w_iterator end = tbeg->second.end();
      for ( ;beg!=end; ++beg)
      {
        if (beg->second == loc)
        {
          tbeg->second.erase(beg);
          if ( tbeg->second.empty() )
            _targets.erase(tbeg);
          return;
        }
        
      }
    }

  }
  
  item front()
  {
    item result(-1, -1, 255);
    t_iterator tbeg = _targets.begin();
    t_iterator tend = _targets.end();
    
    /*if ( tbeg==tend )
      throw;*/
    for ( ;tbeg!=tend; ++tbeg)
    {
      w_iterator itr = tbeg->second.begin();
      if ( result.value > itr->first)
      {
        static_cast<location&>(result) = itr->second;
        result.value = itr->first;
      }
    }
    return result;
  }

  item back()
  {
    item result(-1, -1, 255);
    t_iterator tbeg = _targets.begin();
    t_iterator tend = _targets.end();
    for ( ;tbeg!=tend; ++tbeg)
    {
      w_reverse_iterator itr = tbeg->second.rbegin();
      if ( result.value > itr->first)
      {
        static_cast<location&>(result) = itr->second;
        result.value = itr->first;
        
      }
    }
    return result;
  }

  // Извлекаем ближайших
  wavemap* get_wavemap() const { return _wavemap;}

  void clear()
  {
    _targets.clear();
  }
private:
  targetmap _targets;
  wavemap *_wavemap;
};


#endif